package com.googlecode.lightest.core

import org.testng.reporters.*

/**
 * Extends the TestNG XMLStringBuffer to add newline-omission options.
 */
class XMLStringBuffer2 extends XMLStringBuffer {
    def m_buffer

    /**
     * @param start  A string of spaces indicating the indentation at which
     *               to start the generation.
     */
    XMLStringBuffer2(String start) {
        super(start)
        m_buffer = super.getStringBuffer()
    }

    /**
     * Push a new tag.  Its value is stored and will be compared against the parameter
     * passed to pop().
     * 
     * @param tagName The name of the tag.
     * @param schema The schema to use (can be null or an empty string).
     * @param attributes A Properties file representing the attributes (or null)
     */
    void push(String tagName, String schema, Properties attributes, boolean noNewline) {
        super.push(tagName, schema, attributes)
        if (noNewline) {
            removeEOL()
        }
    }

    /**
     * Push a new tag.  Its value is stored and will be compared against the parameter
     * passed to pop().
     * 
     * @param tagName The name of the tag.
     * @param schema The schema to use (can be null or an empty string).
     */
    void push(String tagName, String schema, boolean noNewline) {
        push(tagName, schema, null, noNewline)
    }
    
    /**
     * Push a new tag.  Its value is stored and will be compared against the parameter
     * passed to pop().
     * 
     * @param tagName The name of the tag.
     * @param attributes A Properties file representing the attributes (or null)
     */
    void push(String tagName, Properties attributes, boolean noNewline) {
        push(tagName, "", attributes, noNewline)
    }
    
    /**
     * Push a new tag.  Its value is stored and will be compared against the parameter
     * passed to pop().
     * 
     * @param tagName The name of the tag.
     * @param noNewline
     */
    void push(String tagName, boolean noNewline) {
        push(tagName, "", noNewline)
    }
    
    /**
     * Pop the last pushed element without verifying it if matches the previously
     * pushed tag.
     * 
     * @param noIndent  no indenting of the closing tag is added if true
     */
    void pop(boolean noIndent) {
        pop(null, noIndent)
    }
    
    /**
     * Pop the last pushed element and throws an AssertionError if it doesn't
     * match the corresponding tag that was pushed earlier.
     * 
     * @param tagName The name of the tag this pop() is supposed to match.
     * @param noIndent  no indenting of the closing tag is added if true
     */
    void pop(String tagName, boolean noIndent) {
        def pos = m_buffer.length()
        super.pop(tagName)
        if (noIndent) {
            removeWhitespace(pos)
        }
    }
    
    /**
     * Add a CDATA tag.
     */
    void addCDATA(String content) {
        def pos = m_buffer.length()
        super.addCDATA(content)
        removeWhitespace(pos)
        removeEOL()
    }
    
    /**
     * Append some content to the current buffer. There is no functionality for
     * adding content within XML tags in XMLStringBuffer, so this can be used
     * for that purpose.
     * 
     * @param content  the content to append to the end of the buffer
     */
    void append(String content) {
        m_buffer.append(content)
    }
    
    /**
     * Removes a single final EOL from the current buffer.
     */
    private void removeEOL() {
        def eol = XMLStringBuffer.EOL
        def pos = m_buffer.length() - eol.length()
        
        if (m_buffer.substring(pos) == eol) {
            m_buffer.delete(pos, pos + eol.length())
        }
    }
    
    /**
     * Removes contiguous whitespace starting from a given position in the
     * current buffer.
     * 
     * @param pos  the index from which to start removing whitespace, inclusive
     */
    private void removeWhitespace(pos) {
        while (m_buffer.charAt(pos) =~ /\s/) {
            m_buffer.deleteCharAt(pos)
        }
    }
}
